package com.android.jr_infraredcamera

import android.hardware.usb.UsbDevice
import android.os.Bundle
import android.util.Log
import android.view.Surface
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.android.jr_infraredcamera.base.BaseFragment
import com.android.jr_infraredcamera.databinding.FragmentUccCameraBinding
import com.android.jr_infraredcamera.utils.UsbSerialPortUtils
import com.android.jr_infraredcamera.utils.toHexString
import com.hoho.android.usbserial.util.SerialInputOutputManager
import com.serenegiant.usb.IFrameCallback
import com.serenegiant.usb.USBMonitor
import com.serenegiant.usb.USBMonitor.OnDeviceConnectListener
import com.serenegiant.usb.USBMonitor.UsbControlBlock
import com.serenegiant.usb.UVCCamera
import com.vmark.ffmpeglib.Ffmpeg
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"

/**
 * A simple [Fragment] subclass.
 * Use the [UccCameraFragment.newInstance] factory method to
 * create an instance of this fragment.
 */
class UccCameraFragment : BaseFragment<FragmentUccCameraBinding>(R.layout.fragment_ucc_camera) {
    // TODO: Rename and change types of parameters
    private var param1: String? = null
    private var param2: String? = null

    companion object {
        /**
         * Use this factory method to create a new instance of
         * this fragment using the provided parameters.
         *
         * @param param1 Parameter 1.
         * @param param2 Parameter 2.
         * @return A new instance of fragment UccCameraFragment.
         */
        // TODO: Rename and change types and number of parameters
        @JvmStatic
        fun newInstance(param1: String, param2: String) = UccCameraFragment().apply {
            arguments = Bundle().apply {
                putString(ARG_PARAM1, param1)
                putString(ARG_PARAM2, param2)
            }
        }

        private const val TAG = "===UccCameraFragment==="
    }


    private val mOnDeviceConnectListener: OnDeviceConnectListener? =
        object : OnDeviceConnectListener {
            override fun onAttach(device: UsbDevice) {
                Log.d(
                    TAG,
                    "onAttach: USB设备已连接 vendorId:${device.vendorId}  productId:${device.productId}  ${device.manufacturerName}"
                )
                Toast.makeText(requireContext(), "USB设备已连接", Toast.LENGTH_SHORT).show()
                //4292\11388\1204
                if (device.vendorId == 1204 || device.vendorId == 2760 || device.vendorId == 1105 || device.vendorId==1409) {
                    mUSBMonitor?.requestPermission(device)
                }
            }

            override fun onConnect(
                device: UsbDevice,
                ctrlBlock: UsbControlBlock,
                createNew: Boolean,
            ) {
                Log.d(
                    TAG,
                    "onConnect: $device  vendorId:${device.vendorId}  productId:${device.productId}"
                )
             /*   if (device.vendorId == 1105) {
                    Thread {
                        UsbSerialPortUtils.getInstance().openSerial(device)
                    }.start()
                }*/

                if (device.vendorId == 1204 || device.vendorId == 2760 ||device.vendorId==1409) {
                    Thread {
                        // 打开摄像头
                        // 打开摄像头
                        mUVCCamera = UVCCamera()
                        mUVCCamera?.open(ctrlBlock)

                        // 设置预览大小和像素格式，此处采用 YUYV 格式（即 YUV422），也可以根据需要改为其他格式
//                        val previewWidth = 1280
//                        val previewHeight = 512
//                        mUVCCamera?.setPreviewSize(
//                            previewWidth, previewHeight, UVCCamera.FRAME_FORMAT_YUYV
//                        )

                        // 设置帧回调，获取实时帧数据
                        mUVCCamera?.setFrameCallback(IFrameCallback { frame ->
                            // 此处获取的 frame 数据为原始帧数据，大小和格式与预览设置一致
                            val size = frame.remaining()
                            Log.d(
                                TAG, "${System.currentTimeMillis()}=====Received frame, size: $size"
                            )
                            Ffmpeg.getInstance().pushStreamData(frame)
                            // 可在此处添加解析代码，将 YUV422 数据拆分成两部分（例如一部分用于推流、一部分用于温度数据）
                        }, UVCCamera.FRAME_FORMAT_YUYV)

                        // 设置预览显示的 Surface
                        CoroutineScope(Dispatchers.Main).launch {
                            mUVCCamera?.setPreviewDisplay(Surface(binding.mUVCCameraView.surfaceTexture))
                            mUVCCamera?.startPreview()
                        }
                    }.start()
                }

            }

            override fun onDisconnect(device: UsbDevice, ctrlBlock: UsbControlBlock) {
                Log.d(
                    TAG,
                    "onDisconnect: $device  vendorId:${device.vendorId}  productId:${device.productId}"
                );
                if (mUVCCamera != null) {
                    mUVCCamera?.stopPreview()
                    mUVCCamera?.close()
                    mUVCCamera?.destroy()
                    mUVCCamera = null
                }
            }

            override fun onDettach(device: UsbDevice) {
                Log.d(
                    TAG,
                    "onDettach: USB设备已拔出  vendorId:${device.vendorId}  productId:${device.productId}"
                )
                Toast.makeText(requireContext(), "USB设备已拔出", Toast.LENGTH_SHORT).show()
            }

            override fun onCancel(device: UsbDevice) {
                Log.d(TAG, "onCancel")
            }
        }

    private var mUSBMonitor: USBMonitor? = null

    private var mUVCCamera: UVCCamera? = null


    override fun initData() {
        CoroutineScope(Dispatchers.IO).launch {
            mUSBMonitor = USBMonitor(requireContext(), mOnDeviceConnectListener)
            mUSBMonitor?.register()
        }


    }

    override fun initView() {

        UsbSerialPortUtils.getInstance().initUsb(object : SerialInputOutputManager.Listener {
            override fun onNewData(data: ByteArray?) {
                Log.e(TAG, "onNewData: =====返回的数据===${data?.toHexString(true)}")
            }

            override fun onRunError(e: Exception?) {
                Log.e(TAG, "onRunError: ========$e")
            }
        })
        binding.mSerialSendBtn.setOnClickListener {

            val cleanedHexString =
                binding.mSerialMsgEdit.text.toString().replace("\\s".toRegex(), "")
            val len = cleanedHexString.length
            val data = ByteArray(len / 2)

            for (i in 0 until len step 2) {
                val hexPair = cleanedHexString.substring(i, i + 2)
                data[i / 2] = hexPair.toInt(16).toByte()
            }
            CoroutineScope(Dispatchers.IO).launch {
                Log.e(TAG, "port: ===write===${data.toHexString(true)}")
                UsbSerialPortUtils.getInstance().sendData(data)
//                val boolean = SerialPortUtils.getInstance()
//                    .sendData(SerialPortEnum.SERIAL_ONE, data, 3000)
//                withContext(
//                    Dispatchers.Main
//                ) {
//                    Toast.makeText(requireActivity(), "==消息发送结果:$boolean", Toast.LENGTH_SHORT)
//                        .show()
//                }
            }
        }

        binding.mGetTmp.setOnClickListener {
            val x = binding.mGetTmpX.text.toString().toIntOrNull() ?: 0
            val y = binding.mGetTmpY.text.toString().toIntOrNull() ?: 0
            if (x > 640 || y > 512) {
                Toast.makeText(requireActivity(), "坐标不合法", Toast.LENGTH_SHORT).show()
                return@setOnClickListener
            }
            CoroutineScope(Dispatchers.IO).launch {
                val tmp = Ffmpeg.getInstance().getTemperatureFromFrame(x, y)
                withContext(Dispatchers.Main) {
                    Toast.makeText(requireActivity(), "坐标温度==${tmp}", Toast.LENGTH_SHORT).show()

                }
            }
        }

        binding.mSerialSendBtn2.setOnClickListener {

            val cleanedHexString =
                binding.mSerialMsgEdit2.text.toString().replace("\\s".toRegex(), "")
            val len = cleanedHexString.length
            val data = ByteArray(len / 2)

            for (i in 0 until len step 2) {
                val hexPair = cleanedHexString.substring(i, i + 2)
                data[i / 2] = hexPair.toInt(16).toByte()
            }

            val size = binding.mSerialSizeEdit2.text.toString().toIntOrNull() ?: -1
            CoroutineScope(Dispatchers.IO).launch {
                Log.e(TAG, "port: ===write===${data.toHexString(true)}")
                val data = UsbSerialPortUtils.getInstance().writeAndReadData(data, size)
                Log.e(TAG, "initView: ======data===${data?.toHexString(true)}")

//                val boolean = SerialPortUtils.getInstance()
//                    .sendData(SerialPortEnum.SERIAL_ONE, data, 3000)
//                withContext(
//                    Dispatchers.Main
//                ) {
//                    Toast.makeText(requireActivity(), "==消息发送结果:$boolean", Toast.LENGTH_SHORT)
//                        .show()
//                }
            }
        }
    }

    override fun initObservable() {

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        arguments?.let {
            param1 = it.getString(ARG_PARAM1)
            param2 = it.getString(ARG_PARAM2)
        }
    }


    override fun onStart() {
        super.onStart()
        mUSBMonitor?.register()
    }


    override fun onStop() {
        super.onStop()

    }

    override fun onDestroy() {
        if (mUSBMonitor != null) {
            mUSBMonitor?.destroy();
            mUSBMonitor = null;
        }
        super.onDestroy();
    }

    override fun onPause() {
        super.onPause()
        if (mUVCCamera != null) {
            mUVCCamera?.stopPreview()
            mUVCCamera?.close()
            mUVCCamera?.destroy()
            mUVCCamera = null
        }
        if (mUSBMonitor != null) {
            mUSBMonitor?.unregister()
        }
    }


}